﻿import pygame
import sys
import math
from pygame.locals import *

# 初始化 Pygame
pygame.init()

# 计算器常量
WINDOW_WIDTH = 320
WINDOW_HEIGHT = 480
BUTTON_SIZE = 70
BUTTON_MARGIN = 10
DISPLAY_HEIGHT = 120

# 颜色定义
BACKGROUND = (40, 44, 52)
DISPLAY_BG = (30, 34, 42)
BUTTON_NUMBER = (72, 84, 96)
BUTTON_OPERATOR = (255, 159, 67)
BUTTON_FUNCTION = (97, 175, 239)
BUTTON_SPECIAL = (241, 196, 15)
TEXT_COLOR = (220, 220, 220)
TEXT_SECONDARY = (150, 150, 150)

# 创建游戏窗口
screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
pygame.display.set_caption('Pygame 计算器')
clock = pygame.time.Clock()

# 加载字体
try:
    # 尝试加载中文字体
    font_large = pygame.font.Font('simhei.ttf', 32)
    font_medium = pygame.font.Font('simhei.ttf', 24)
    font_small = pygame.font.Font('simhei.ttf', 18)
except:
    # 如果无法加载中文字体，使用系统默认字体
    font_large = pygame.font.SysFont(None, 32)
    font_medium = pygame.font.SysFont(None, 24)
    font_small = pygame.font.SysFont(None, 18)

class Calculator:
    def __init__(self):
        self.current_input = "0"
        self.previous_input = ""
        self.operation = None
        self.should_reset_input = False
        self.memory = 0
        self.history = []
    
    def input_digit(self, digit):
        if self.should_reset_input or self.current_input == "0":
            self.current_input = str(digit)
            self.should_reset_input = False
        else:
            self.current_input += str(digit)
    
    def input_decimal(self):
        if self.should_reset_input:
            self.current_input = "0."
            self.should_reset_input = False
        elif "." not in self.current_input:
            self.current_input += "."
    
    def clear(self):
        self.current_input = "0"
        self.should_reset_input = False
    
    def clear_all(self):
        self.current_input = "0"
        self.previous_input = ""
        self.operation = None
        self.should_reset_input = False
    
    def delete_last(self):
        if len(self.current_input) > 1:
            self.current_input = self.current_input[:-1]
        else:
            self.current_input = "0"
    
    def set_operation(self, op):
        if self.operation and not self.should_reset_input:
            self.calculate()
        
        self.previous_input = self.current_input
        self.operation = op
        self.should_reset_input = True
    
    def calculate(self):
        if self.operation is None or self.should_reset_input:
            return
        
        try:
            a = float(self.previous_input)
            b = float(self.current_input)
            result = 0
            
            if self.operation == "+":
                result = a + b
            elif self.operation == "-":
                result = a - b
            elif self.operation == "×":
                result = a * b
            elif self.operation == "÷":
                if b == 0:
                    self.current_input = "错误: 除零"
                    self.should_reset_input = True
                    return
                result = a / b
            elif self.operation == "%":
                result = a % b
            
            # 处理结果格式
            if result.is_integer():
                self.current_input = str(int(result))
            else:
                self.current_input = str(round(result, 10)).rstrip('0').rstrip('.')
            
            # 添加到历史记录
            self.history.append(f"{a} {self.operation} {b} = {self.current_input}")
            if len(self.history) > 5:
                self.history.pop(0)
            
            self.operation = None
            self.should_reset_input = True
            
        except ValueError:
            self.current_input = "错误"
            self.should_reset_input = True
    
    def calculate_percentage(self):
        try:
            value = float(self.current_input) / 100
            if value.is_integer():
                self.current_input = str(int(value))
            else:
                self.current_input = str(value)
        except ValueError:
            self.current_input = "错误"
            self.should_reset_input = True
    
    def toggle_sign(self):
        if self.current_input != "0":
            if self.current_input.startswith("-"):
                self.current_input = self.current_input[1:]
            else:
                self.current_input = "-" + self.current_input
    
    def memory_add(self):
        try:
            self.memory += float(self.current_input)
        except ValueError:
            pass
    
    def memory_subtract(self):
        try:
            self.memory -= float(self.current_input)
        except ValueError:
            pass
    
    def memory_recall(self):
        if self.memory.is_integer():
            self.current_input = str(int(self.memory))
        else:
            self.current_input = str(self.memory)
    
    def memory_clear(self):
        self.memory = 0

class Button:
    def __init__(self, x, y, width, height, text, color, text_color=TEXT_COLOR):
        self.rect = pygame.Rect(x, y, width, height)
        self.text = text
        self.color = color
        self.text_color = text_color
        self.hover = False
    
    def draw(self, surface):
        # 绘制按钮背景
        pygame.draw.rect(surface, self.color, self.rect, border_radius=8)
        
        # 如果鼠标悬停，添加高亮效果
        if self.hover:
            highlight = pygame.Surface((self.rect.width, self.rect.height), pygame.SRCALPHA)
            pygame.draw.rect(highlight, (255, 255, 255, 30), (0, 0, self.rect.width, self.rect.height), border_radius=8)
            surface.blit(highlight, self.rect)
        
        # 绘制按钮边框
        pygame.draw.rect(surface, (60, 60, 60), self.rect, 2, border_radius=8)
        
        # 绘制按钮文本
        text_surface = font_medium.render(self.text, True, self.text_color)
        text_rect = text_surface.get_rect(center=self.rect.center)
        surface.blit(text_surface, text_rect)
    
    def is_clicked(self, pos):
        return self.rect.collidepoint(pos)
    
    def update_hover(self, pos):
        self.hover = self.rect.collidepoint(pos)

class CalculatorApp:
    def __init__(self):
        self.calculator = Calculator()
        self.buttons = self.create_buttons()
    
    def create_buttons(self):
        buttons = []
        
        # 按钮布局定义
        button_layout = [
            # 第一行: 内存功能按钮
            ["MC", "MR", "M+", "M-", "C"],
            # 第二行: 清除和删除
            ["CE", "DEL", "%", "÷"],
            # 第三行: 数字和操作符
            ["7", "8", "9", "×"],
            # 第四行: 数字和操作符
            ["4", "5", "6", "-"],
            # 第五行: 数字和操作符
            ["1", "2", "3", "+"],
            # 第六行: 数字和等号
            ["±", "0", ".", "="]
        ]
        
        # 按钮颜色映射
        color_map = {
            "MC": BUTTON_FUNCTION, "MR": BUTTON_FUNCTION, 
            "M+": BUTTON_FUNCTION, "M-": BUTTON_FUNCTION,
            "C": BUTTON_SPECIAL, "CE": BUTTON_SPECIAL,
            "DEL": BUTTON_SPECIAL, "±": BUTTON_SPECIAL,
            "%": BUTTON_OPERATOR, "÷": BUTTON_OPERATOR,
            "×": BUTTON_OPERATOR, "-": BUTTON_OPERATOR,
            "+": BUTTON_OPERATOR, "=": BUTTON_OPERATOR,
            "0": BUTTON_NUMBER, "1": BUTTON_NUMBER,
            "2": BUTTON_NUMBER, "3": BUTTON_NUMBER,
            "4": BUTTON_NUMBER, "5": BUTTON_NUMBER,
            "6": BUTTON_NUMBER, "7": BUTTON_NUMBER,
            "8": BUTTON_NUMBER, "9": BUTTON_NUMBER,
            ".": BUTTON_NUMBER
        }
        
        # 创建按钮对象
        for row_idx, row in enumerate(button_layout):
            for col_idx, text in enumerate(row):
                x = BUTTON_MARGIN + col_idx * (BUTTON_SIZE + BUTTON_MARGIN)
                y = DISPLAY_HEIGHT + BUTTON_MARGIN + row_idx * (BUTTON_SIZE + BUTTON_MARGIN)
                
                # 等号按钮高度是其他按钮的两倍
                height = BUTTON_SIZE * 2 + BUTTON_MARGIN if text == "=" else BUTTON_SIZE
                
                # 数字0的宽度是其他按钮的两倍
                width = BUTTON_SIZE * 2 + BUTTON_MARGIN if text == "0" else BUTTON_SIZE
                
                buttons.append(Button(x, y, width, height, text, color_map[text]))
        
        return buttons
    
    def handle_button_click(self, button_text):
        if button_text in "0123456789":
            self.calculator.input_digit(button_text)
        elif button_text == ".":
            self.calculator.input_decimal()
        elif button_text == "C":
            self.calculator.clear_all()
        elif button_text == "CE":
            self.calculator.clear()
        elif button_text == "DEL":
            self.calculator.delete_last()
        elif button_text == "±":
            self.calculator.toggle_sign()
        elif button_text == "%":
            self.calculator.calculate_percentage()
        elif button_text in ["+", "-", "×", "÷"]:
            self.calculator.set_operation(button_text)
        elif button_text == "=":
            self.calculator.calculate()
        elif button_text == "MC":
            self.calculator.memory_clear()
        elif button_text == "MR":
            self.calculator.memory_recall()
        elif button_text == "M+":
            self.calculator.memory_add()
        elif button_text == "M-":
            self.calculator.memory_subtract()
    
    def draw(self, surface):
        # 绘制背景
        surface.fill(BACKGROUND)
        
        # 绘制显示区域
        display_rect = pygame.Rect(0, 0, WINDOW_WIDTH, DISPLAY_HEIGHT)
        pygame.draw.rect(surface, DISPLAY_BG, display_rect)
        pygame.draw.line(surface, (60, 60, 60), (0, DISPLAY_HEIGHT), (WINDOW_WIDTH, DISPLAY_HEIGHT), 2)
        
        # 绘制当前输入
        current_text = self.calculator.current_input
        if len(current_text) > 12:
            current_text = current_text[:12] + "..."
        
        text_surface = font_large.render(current_text, True, TEXT_COLOR)
        text_rect = text_surface.get_rect(bottomright=(WINDOW_WIDTH - 20, DISPLAY_HEIGHT - 20))
        surface.blit(text_surface, text_rect)
        
        # 绘制运算表达式（如果有）
        if self.calculator.operation and self.calculator.previous_input:
            expression = f"{self.calculator.previous_input} {self.calculator.operation}"
            expr_surface = font_small.render(expression, True, TEXT_SECONDARY)
            expr_rect = expr_surface.get_rect(topright=(WINDOW_WIDTH - 20, 20))
            surface.blit(expr_surface, expr_rect)
        
        # 绘制内存指示器（如果有内存值）
        if self.calculator.memory != 0:
            memory_text = "M"
            memory_surface = font_small.render(memory_text, True, BUTTON_FUNCTION)
            memory_rect = memory_surface.get_rect(topleft=(20, 20))
            surface.blit(memory_surface, memory_rect)
        
        # 绘制历史记录
        for i, history_item in enumerate(self.calculator.history):
            history_surface = font_small.render(history_item, True, TEXT_SECONDARY)
            history_rect = history_surface.get_rect(topleft=(20, 50 + i * 20))
            surface.blit(history_surface, history_rect)
        
        # 绘制所有按钮
        for button in self.buttons:
            button.draw(surface)
    
    def update(self, mouse_pos):
        # 更新按钮的悬停状态
        for button in self.buttons:
            button.update_hover(mouse_pos)

# 主函数
def main():
    app = CalculatorApp()
    running = True
    
    while running:
        mouse_pos = pygame.mouse.get_pos()
        
        # 处理事件
        for event in pygame.event.get():
            if event.type == QUIT:
                running = False
            elif event.type == MOUSEBUTTONDOWN:
                if event.button == 1:  # 左键点击
                    for button in app.buttons:
                        if button.is_clicked(event.pos):
                            app.handle_button_click(button.text)
                            break
        
        # 更新应用状态
        app.update(mouse_pos)
        
        # 绘制应用
        app.draw(screen)
        
        # 更新显示
        pygame.display.flip()
        
        # 控制帧率
        clock.tick(60)
    
    pygame.quit()
    sys.exit()

if __name__ == "__main__":
    main()